#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "NativeMath.h"


BOOL isnegative(const ninteger* value) 
{
	return value->issigned && getbit(value, value->width - 1u);
}

BOOL iszeroarr(const uintarray* content) 
{
	int i;
	for(i = 0; i < content->length; i++)
	{
		if(content->values[i] != 0)
		{
			return FALSE;
		}
	}
	return TRUE;
}

BOOL iszero(const ninteger* value) 
{
	return iszeroarr(value->content);
}


EXPORT BOOL areequal(const ninteger* a, const ninteger* b)
{
	const ninteger* shortest = a->content->length > b->content->length ? b : a;
	const ninteger* longest = a->content->length > b->content->length ? a : b;

	int i = 0;
	for (; i < shortest->content->length; i++)
		if (shortest->content->values[i] != longest->content->values[i])
			return FALSE;

	if (isnegative(shortest)) // shortest is signed and LESS THAN zero
	{
		// longest MUST be signed
		if (!longest->issigned)
			return FALSE;

		// and have only sign bits 
		for (; i < longest->content->length; i++)
			if (longest->content->values[i] != BASE_MAX_VALUE)
				return FALSE;
	}
	else 
	{
		for (; i < longest->content->length; i++)
			if (longest->content->values[i] != 0)
				return FALSE;
	}

	return TRUE;
}

BOOL isgreaterinternal(const uintarray* a, const uintarray* b) 
{
	const uintarray* shortest = a->length > b->length ? b : a;
	const uintarray* longest = a->length > b->length ? a : b;

	int i = longest->length - 1;

	for (; i >= shortest->length; i--)
		if (longest->values[i] != 0)
			return FALSE;

	for (; i >= 0; i--)
		if (longest->values[i] > shortest->values[i])
			return (longest == a);
		else if (longest->values[i] < shortest->values[i])
			return (shortest == a);

	return FALSE;
}

EXPORT BOOL isgreater(const ninteger* a, const ninteger* b)
{
	if (a->issigned && b->issigned)
	{
		BOOL aIsNegative = isnegative(a);
		BOOL bIsNegative = isnegative(b);

		if (aIsNegative && !bIsNegative)
			return FALSE;
		else if (!aIsNegative && bIsNegative)
			return TRUE;
		else
		{
			uintarray* ar = a->content;
			uintarray* br = b->content;

			if (aIsNegative) // means that b is also
			{
				negateinternal(ar, ar);
				negateinternal(br, br);

				return isgreaterinternal(br, ar);
			}

			return isgreaterinternal(ar, br);
		}
	}
	else if (!a->issigned && !b->issigned)
	{
		return isgreaterinternal(a->content, b->content);
	}
	else if (a->issigned) // and ! b.Signed
	{
		return isnegative(a) ? FALSE : isgreaterinternal(a->content, b->content);
	}
	else // if b.Signed and ! a.Signed
	{
		return isnegative(b) ? TRUE : isgreaterinternal(a->content, b->content);
	}
}